package thread;

/**
 * Created with IntelliJ IDEA
 * <p>
 * Description:
 * 构成线程安全问题的一个原因就是多个线程在读写同一个变量，
 * 所以计算这个数组，就要用两个变量，每一个线程用一个。
 * <p>
 * User:34398
 * Date:2024-07-17
 * Time:20:24
 */


/**
 * 下面枷锁操作是在两个线程都枷锁的前提下
 * 而且是针对同一个对象加锁的
 *
 * 有几个对象，代表有几个锁
 *
 * 两个线程都要加锁原因是如果有一个没有加，那么那个线程可以无视另一个线程的锁，直接抢占执行
 * */


//锁对象的作用：
    /**
     * 锁对象是用来区分多个线程，是否针对同一个“对象”枷锁
     * synchronized填的什么对象不重要，重要的是是否需要一致的对象
     * 同一个对象，线程之间就会出现阻塞，既锁竞争/锁冲突
     * 不同锁对象的线程之间，相互不干涉，不会出现阻塞现象*/


    /*
    *
    * 如果对多个线程加同一个锁，谁先拿到锁，跟系统调度有关（随机调度），是不确定的
    * 一个线程释放锁之后，其他线程那个拿到锁同样也是不确定的
    * */



public class CaculateArr {
    private static long sum1 = 0;
    private static long sum2 = 0;
    private static long all = 5000000;
private static Object locker=new Object();
    public static void main(String[] args) throws InterruptedException {
        long beg = System.currentTimeMillis();

        long[] arr = new long[(int) all];
        for (int i = 0; i < all; i++) {


            //synchronized(demo1.class)不常见，但是本质是一样的.java javac编译成
            // .class文件 加载到内存运行，形成对应对象
            synchronized(locker){
                sum2+=arr[i];
            }

            arr[i] = i + 1;
        }
        Thread thread1 = new Thread(() -> {
            for (int i = 0; i < all; i += 2) {//偶数
                synchronized(locker){
                    sum1 += arr[i];
                }
            }
        });
        Thread thread2 = new Thread(() -> {
            for (int i = 1; i < all; i += 2) {
                sum2 += arr[i];
            }
        });

        thread1.start();
        thread2.start();
        thread1.join();
        thread2.join();
        long end = System.currentTimeMillis();

        System.out.println("sum1=" + sum1);
        System.out.println("sum2=" + sum2);
        long sum = sum1 + sum2;
        System.out.println("sum=" + sum);
        long time = end - beg;
        System.out.println("时间：" + time);


    }
}
